package com.learn.intercecptor;

import com.learn.Mask;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.stream.Stream;

/**
 * 数据脱敏拦截器
 *
 * @author: liyf
 * @create: 2025-02-15 22:50
 **/
@Intercepts(
        @Signature(
                type = ResultSetHandler.class,
                method = "handleResultSets",
                args = Statement.class

        )
)
public class MaskInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object proceed = invocation.proceed();
        if (proceed instanceof List) {
            List<Object> records = (List<Object>) proceed;
            records.forEach(this::mask);
        }

        return proceed;
    }

    private void mask(Object o) {
        // 获取属性名
        Class<?> souceClass = o.getClass();

        Class<?> userClass = getUserClass(o);

        System.out.println("souceClass.getName(): " + souceClass.getName());
        System.out.println("userClass.getName(): " + userClass.getName());

        // 用于属性值
        MetaObject metaObject = SystemMetaObject.forObject(o);


        Field[] declaredFields = userClass.getDeclaredFields();

        for (Field declaredField : declaredFields) {
            boolean annotationPresent = declaredField.isAnnotationPresent(Mask.class);
            System.out.println(declaredField.getName() + "----" + annotationPresent);
        }

        Stream.of(declaredFields).filter(f->f.isAnnotationPresent(Mask.class))
                .forEach(field -> doMask(metaObject, field));


    }

    private void doMask(MetaObject metaObject, Field field) {

        // 获取 属性名
        String name = field.getName();

        // 获取属性值
        Object value = metaObject.getValue(name);

        if (value != null && String.class == metaObject.getGetterType(name)) {
            Mask annotation = field.getAnnotation(Mask.class);
            String apply = annotation.mask().getDesensitizer().apply((String) value);
            metaObject.setValue(name, apply);
        }
    }

    private Class<?> getUserClass(Object o) {
        Class<?> clazz = o.getClass();
        while (clazz != null && clazz.getName().contains("$$")) {
            clazz = clazz.getSuperclass();
        }
        return clazz;
    }

}
